﻿using System;
using System.Collections.Generic;
using System.Data.Objects.DataClasses;
using System.Linq;
using Diploma.Models.Entities;
using Diploma.Models.IRepositories;
using Microsoft.Office.Interop.Word;

namespace Diploma.Models.Repositories
{
    internal class OrderPracticeRepository : IOrderPracticeRepository
    {
        private readonly DiplomaEntities dataContext;

        public OrderPracticeRepository(DiplomaEntities dataContext)
        {
            this.dataContext = dataContext;
        }

        /// <summary>
        /// Получание приказа на практику
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public OrderPractice GetOrder(Guid id)
        {
            OrderPractice model = dataContext.OrderPractices.FirstOrDefault(r => r.Id == id);
            return model;
        }

        /// <summary>
        /// Создание нового документа
        /// </summary>
        /// <param name="orderPractice"></param>
        public void CreateOrder(OrderPractice orderPractice)
        {
            if (orderPractice != null)
                dataContext.OrderPractices.AddObject(orderPractice);
            dataContext.SaveChanges();
        }

        /// <summary>
        /// Сохранение состояния информации на данный момент
        /// </summary>
        /// <param name="orderPractice"></param>
        /// <param name="startDate"></param>
        /// <param name="stopDate"></param>
        public void SaveState(OrderPractice orderPractice, DateTime startDate, DateTime stopDate)
        {
            if (orderPractice.Students == null)
                throw new ArgumentNullException("orderPractice");

            if (orderPractice.Students.Count() == 0)
                throw new ArgumentNullException("orderPractice");

            int i = 1;
            foreach (Student item in orderPractice.Students)
            {
                
                var saveState = new SaveStateOrderPractice
                                    {
                                        OrderPracticeId = orderPractice.Id,
                                        Num = i,
                                        Fio = item.FullName,
                                        StudentGroup = item.StudentsGroup.Name,
                                        PracticePlace = GetStudentPricticePlaceName(item),
                                        LecturerPractice =
                                            item.CollaborationRoom != null
                                                ? item.CollaborationRoom.Lecturer != null
                                                      ? item.CollaborationRoom.Lecturer.FullName
                                                      : ""
                                                : "",
                                        Theme = item.CollaborationRoom != null ? item.CollaborationRoom.BaseTheme : "",
                                        LecturerDiplom =
                                            item.CollaborationRoom != null
                                                ? item.CollaborationRoom.Lecturer != null
                                                      ? item.CollaborationRoom.Lecturer.FullName
                                                      : ""
                                                : "",
                                        Note =
                                            item.CollaborationRoom != null ? item.CollaborationRoom.BaseDescription : "",
                                        Counsultant =
                                            item.CollaborationRoom != null
                                                ? item.CollaborationRoom.Consultant.FullName
                                                : ""
                                    };
                orderPractice.SaveStateOrderPractices.Add(saveState);
                i++;
            }
            dataContext.SaveChanges();
        }

        public IEnumerable<OrderPractice> GetAll()
        {
            return dataContext.OrderPractices;
        }

        public void AttachStudentsToOrder(Guid groupId, Guid orderId)
        {
            IQueryable<Student> students = dataContext.Users.OfType<Student>().Where(r => r.StudentsGroupId == groupId);
            OrderPractice order = GetOrder(orderId);

            if (students.Count() == 0)
                throw new Exception("Can't find student in group");
            if (order == null)
                throw new NullReferenceException("Can't find order");

            foreach (Student student in students)
            {
                order.Students.Add(student);
            }

            dataContext.SaveChanges();
        }

        public void RemoveStudentsFromOrder(Guid studentId, Guid orderId)
        {
            Student students = dataContext.Users.OfType<Student>().FirstOrDefault(r => r.UserId == studentId);
            OrderPractice order = GetOrder(orderId);

            if (students == null)
                throw new NullReferenceException("Can't find student");
            if (order == null)
                throw new NullReferenceException("Can't find order");

            order.Students.Remove(students);
        }

        public void SaveState(Guid orderId, IEnumerable<StudentEntity> students)
        {
            OrderPractice order = GetOrder(orderId);

            if (students == null || !students.Any())
                throw new Exception("Order doesn't have students.");

            order.SaveStateOrderPractices.Clear();
            dataContext.SaveChanges();

            int i = 1;
            foreach (StudentEntity item in students)
            {
                var saveStudent = new SaveStateOrderPractice
                                      {
                                          Id = Guid.NewGuid(),
                                          OrderPracticeId = order.Id,
                                          Num = i,
                                          Fio = item.FIO,
                                          StudentGroup = item.GroupName,
                                          PracticePlace = item.PracticePlaceName,
                                          LecturerPractice = item.LecturerPractice,
                                          LecturerDiplom = item.LecturerDiplom,
                                          Theme = item.Theme,
                                          Note = item.Note,
                                          Counsultant = item.Consultant,
                                          StudentId = item.Id
                                      };
                order.SaveStateOrderPractices.Add(saveStudent);
                i++;
            }

            order.IsVerify = true;
            order.UpdateDate = DateTime.Now;
            dataContext.SaveChanges();
        }

        public SaveStateOrderPractice GetStudentFromSSOP(Guid studentId)
        {
            SaveStateOrderPractice student = dataContext.SaveStateOrderPractices.FirstOrDefault(r => r.StudentId == studentId);
            if (student != null)
                return student;
            throw new Exception("Can't find student");
        }

        public void Delete(Guid orderId)
        {
            var order = DataManager.Instance.OrderPracticeRepository.GetOrder(orderId);
            dataContext.OrderPractices.DeleteObject(order);
            dataContext.SaveChanges();
        }

        public void SaveChanges()
        {
            dataContext.SaveChanges();
        }

        #region Private

        private string GetStudentPricticePlaceName(Student item)
        {
            var practicePlaceName = String.Empty;
            if (item.CollaborationRoom != null)
            {
                if (item.CollaborationRoom.PracticePlace.HasValue)
                {
                    practicePlaceName = DataManager.Instance.CompaniesRepository.Get(item.CollaborationRoom.PracticePlace.Value).
                           DisplayName;
                }
            }

            return practicePlaceName;
        }

        #endregion
    }
}
